--[=[
 规则
 白球或黑球进完算赢
 有红球的是要进了红球后再进一个别的球， 如果不进就退回红球
 如果只剩下红球则退回一个进球
 积分场：每个球代表一个分数， 拿到指定分数算赢

]=]


local Ball = require(".games.snooker.ball")

local table_insert = table.insert
local table_remove = table.remove
local math_random = math.random

local M = class("Rule")






-- to localeger
local function int(f)
    if f >= 0 then return math.floor(f)
    else return math.ceil(f)
    end
end

------------------------------------------------

local win_width = 800
local win_height = 500
local BALL =
{
    -- local X, Y, dir, gapt 球的坐标，方向，摩擦力
    -- local kind 球的类型 0-7
    -- local stop, goin 球是否停止，是否进洞
    -- LONGLONG Lt1, Lt2 时间，Lt2-Lt1 > gapt 决定球运动时间长短
}




-- 减速时的加速度
local slow = { 0.01, 0.02, 0.05, 0.1, 0.11, 0.14 }


local function gettime()
    return g.getMsec()
end


function M:ctor()
    -- 球的初始坐标
    self.iix = { 0,
                 1, 1,
                 2, 2, 2,
                 3, 3, 3, 3,
                 4, 4, 4, 4, 4,
                 180, 180, 180, 400, 581, 740, 100 }

    self.iiy = { 0,
                 -1, 1,
                 -2, 0, 2,
                 -3, -1, 1, 3,
                 -4, -2, 0, 2, 4,
                 350, 150, 250, 250, 250, 250, 200 }

    --0母球，1白色， 2黑色， 3红色
    self.tb_pos = {
        {x=0, y = 0, id=1, color=0 },
        --白
        { x = -66, y = 0, id=2, color=1 },
        { x = -33, y = 57, id=4, color=1 },
        { x = -33, y = -19, id=6, color=1 },
        { x = -33, y = -57, id=7, color=1 },
        { x = 0, y = 38, id=9, color=1 },
        { x = 33, y = 57, id=13, color=1 },
        { x = 33, y = -19, id=15, color=1 },
        { x = 33, y = -57, id=16, color=1 },
        { x = 66, y = 8, id=18, color=1 },
        --红
        --{ x = 0, y = 0, id=10, color=3 },
        --黑
        { x = -66, y = -38, id=3, color=2 },
        { x = 0, y = -38, id=11, color=2 },
        { x = 0, y = -76, id=12, color=2 },
        { x = 33, y = 19, id=14, color=2 },
        { x = 66, y = 38, id=17, color=2 },
        { x = 66, y = -38, id=19, color=2 },
        { x = -66, y = 38, id=20, color=2 },
        { x = 0, y = 76, id=8, color=2 },
        { x = -33,y = 19, id=5, color=2 },
    }
    if g.room_cfg.type == 2 then
        table_insert(self.tb_pos,{ x = 0, y = -200, id=10, color=3 })
    end

    --桌子的边界
    self.sx = 38
    self.ex = 762
    self.sy = 38
    self.ey = 462

    --6个洞的坐标
    self.holes = {
        {x=28, y=28},
        {x=28, y=472},
        {x=400, y=25},
        {x=400, y=475},
        {x=772, y=28},
        {x=772, y=472},
    }

    --球的个数
    self.balls_num = 22
    self.cue_ball_id = 1
    --移动速度
    self.speed = 3

    self.r = 13 --小球半径
    self.R = 26 --小球直径
    self.ball_r = 13 --球半径
    self.ball_R = 26
    self.balls = {}
    self.win_kind = 0 --赢的球类型
    --0母球，1白色， 2黑色， 3红色
    self.color_c = 0
    self.color_w = 1
    self.color_b = 2
    self.color_r = 3

    self:shuffle()
end

function M:shuffle()
    self.tb_pos = {
        { x = 0, y = 0, id = 1, color = 0 },
        { x = -68, y = 40, id = 10, color = 2 },
        { x = -68, y = 0, id = 2, color = 1 },
        { x = -68, y = -40, id = 3, color = 2 },
        { x = -34, y = 60, id = 4, color = 1 },
        { x = -34, y = 20, id = 5, color = 2 },
        { x = -34, y = -20, id = 6, color = 1 },
        { x = -34, y = -60, id = 7, color = 1 },
        { x = 0, y = 80, id = 8, color = 2 },
        { x = 0, y = 40, id = 9, color = 1 },
        --{ x = 0, y = 0, id = 10, color = 3 },
        { x = 0, y = -40, id = 11, color = 2 },
        { x = 0, y = -80, id = 12, color = 2 },
        { x = 34, y = 60, id = 13, color = 1 },
        { x = 34, y = 20, id = 14, color = 2 },
        { x = 34, y = -20, id = 15, color = 1 },
        { x = 34, y = -60, id = 16, color = 1 },
        { x = 68, y = 40, id = 17, color = 2 },
        { x = 68, y = 0, id = 18, color = 1 },
        { x = 68, y = -40, id = 19, color = 2 }
    }
    self.win_kind = 0 --赢的球类型
    self.balls = {}
    for k, v in pairs(self.tb_pos) do
        local x = v.x
        local y = v.y
        local id = v.id
        local color = v.color
        local ball = self:addBall(id)
        ball:setPosition(x, y)
        ball:setKind(color)
        self.balls[id] = ball
    end

end

function M:addBall(id)
    local ball = Ball:new(id)
    return ball
end









--取小球
function M:getBallsInfo()
    local balls = {}
    for k, v in pairs(self.balls) do
        local ball = {
            tag = v.kind,
            pos_x = tostring(v.x),
            pos_y = tostring(v.y),
            goin = v.goin,
            vel_x = tostring(v.vx),
            vel_y = tostring(v.vy),
            id = v.id,
        }
        table_insert(balls, ball)
    end
    return balls
end
function M:getBallInfo(id)
    local v = self.balls[id]
    local ball = {
        tag = v.kind,
        pos_x = tostring(v.x),
        pos_y = tostring(v.y),
        goin = v.goin,
        vel_x = tostring(v.vx),
        vel_y = tostring(v.vy),
        id = v.id,
    }
    return ball
end

function M:getBall(id)
    return self.balls[id]
end

function M:setBalls(msg)
    for k, v in pairs(msg.balls) do
        local ball = self.balls[v.id]
        if ball then
            ball.x = tonumber(v.pos_x)
            ball.y = tonumber(v.pos_y)
            ball.vx = tonumber(v.vel_x)
            ball.vy = tonumber(v.vel_y)
            ball.goin = v.goin
        end
    end
end


function M:getWinKind()
    return self.win_kind
end

--取赢球者
function M:getWinner()
    local users = g.desk:getPlayers()
    for k, v in pairs(users) do
        g.log:info("getWinner:", v:getCamp(), self.win_kind)
        if v:getCamp() == self.win_kind then
            return v
        end
    end
    --球没进完，从在玩的人中找赢球的玩家
    local users = g.user_mgr:getPlayingUser() --还在玩的用户赢
    --g.log:deskErr(0, "no winner err", users)
    for k, user in pairs(users) do
        return user
    end

end

--计算打击力度
function M:calculatePower(camp)
    local targetBall = self:chooseBestBall(camp)
    local cueBall = self.balls[self.cue_ball_id]
    local rx = math.random(-13, 13)
    local ry = math.random(-13, 13)
    local t = {x = targetBall.x + rx, y = targetBall.y + ry}

    --计算力度
    local function calculatePointC(x1, y1, x2, y2)
        local dx = x2 - x1
        local dy = y2 - y1
        local dist = math.sqrt(dx*dx + dy*dy)
        local power = math.random(300, 500)
        local ratio = power / dist
        local cx = x1 + dx * ratio
        local cy = y1 + dy * ratio
        return cx, cy
    end
    local x, y = calculatePointC(cueBall.x, cueBall.y, t.x, t.y)
    return x, y
end

--选择打那个球
function M:chooseBestBall(camp)
    local holes = self.holes
    local bestScore = -math.huge
    local balls = self.balls
    local cueBall = balls[self.cue_ball_id]
    local cueBallx = cueBall.x
    local cueBally = cueBall.x
    --print("cueBallx, ", cueBallx, cueBally)
    local bestBall = balls[1]
    for i, ball in ipairs(balls) do
        if i ~= self.cue_ball_id and ball.goin == 0  and ball.kind == camp then -- 不考虑白球
            -- 计算分数：距离远和射角小越好
            local ballx, bally = ball.x, ball.y
            local distance = (cueBallx - ballx)^2 + (cueBally - bally)^2
            local angle = math.abs(math.atan2(bally - cueBally, ballx - cueBallx))
            local score = 1 / (distance * angle + 1) -- 防止除以0
            local radius = self.r
            --print("2222", distance, angle,score)
            -- 计算球到每个球洞的距离，选出最近的那个球洞
            local nearestHole = nil
            local nearestDistance = math.huge
            for j, hole in ipairs(holes) do
                local holeDistance = math.sqrt((ballx - hole.x)^2 + (bally - hole.y)^2)
                if holeDistance > radius and holeDistance < nearestDistance then
                    nearestDistance = holeDistance
                    nearestHole = hole
                end
            end

            -- 如果该球靠近某个球洞，则增加得分
            if nearestHole then
                local weight = 1 - nearestDistance / radius -- 距离越近，权重越大
                score = score + weight * 100 -- 根据需求调整分值
            end
            --print("score", score, bestScore)
            -- 更新最佳球
            if score > bestScore then
                bestScore = score
                bestBall = ball
            end
        end
    end
    print("bestBall:", bestBall.id)
    return bestBall
end

function M:syncBalls(balls)
    --更新球坐标
    self.sx = 38
    self.ex = 762
    self.sy = 38
    self.ey = 462
    for k, v in pairs(balls) do
        local id = v.id
        local ball = self:getBall(id)
        if ball then
            local x = tonumber(v.pos_x)
            local y = tonumber(v.pos_y)
            local vx = tonumber(v.vel_x)
            local vy = tonumber(v.vel_y)
            --if x < self.sx+self.r or x > self.ex-self.r or y < self.sy+self.r or y > self.ey-self.r and ball.goin == 0 then
            --g.log:err("syncBalls:", id, x, y, vx, vy)
            --else
            ball.x = x
            ball.y = y
            ball.vx = vx
            ball.vy = vy
            --end
        else
            g.log:debug("no ball id:", id)
        end

    end

end

--球是否进完了
function M:checkOver(camp)
    if camp <= 0 or camp >= 3 then
        print( "checkOver:",camp, tostring(self.balls))
        return false
    end
    for k, v in pairs(self.balls) do
        if v.kind == camp and v.goin == 0 then
            return false
        end
    end
    --如果红球还没进，把最后进的球退回

    g.log:err("checkOver:", camp)
    self.win_kind = camp
    --所有种类的球都进了
    return true
end

--是否有红球
function M:hasRedBall()
    for k, v in pairs(self.balls) do
        if v:getKind() == 3 then
            return true
        end
    end
    return false
end

return M

